home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2004 #2 / Amiga Plus CD - 2004 - No. 02.iso / AmigaPlus / Tools / Development / AmigaTalk / general / Model.st < prev    next >
Encoding:
Text File  |  2004-01-31  |  10.3 KB  |  340 lines

  1. " -------------------------------------------------------------
  2.   Class Model provides a variant representation for objects 
  3.   that are expected to have dependents.
  4.  
  5.   Instance Variables:
  6.     modelDependents  <nil | Object | DependentsCollection>
  7.  
  8.   Model is an abstract class whose subclasses represent various 
  9.   kinds of information models.  An information model is an 
  10.   object on which user-interface objects such as input fields 
  11.   depend for their data -- thus, the interface objects are 
  12.   said to be dependents of the model.  The Model class provides 
  13.   a fast means of finding dependents.
  14.   
  15.   Here, dependents are kept in an instance variable. 
  16.   For this reason, a new class that is expected to have one or more 
  17.   dependents has to be made a subclass of Model. 
  18.  
  19.   While Model does not provide any new abilities, it has many 
  20.   subclasses that do.  An ApplicationModel mediates between a 
  21.   set of data models and the user interface that is used to 
  22.   manipulate the data.  Various kinds of ValueModel are able to 
  23.   adapt simple data objects so they behave like full-fledged models. 
  24.   --------------------------------------------------------------
  25. "
  26.  
  27. Class Model :Object ! modelDependents modelAdaptors haveAChange linkedMethods !
  28. [
  29.    myAdaptors: aCollectionOrNil
  30.       (aCollectionOrNil == nil)
  31.          ifTrue: [modelAdaptors removeKey: self ifAbsent: []]
  32.         ifFalse: [modelAdaptors at: self put: aCollectionOrNil]
  33. |
  34.    adaptors
  35.       ^ modelAdaptors at: self ifAbsent: []
  36. |
  37.    dependenciesAt: anObject
  38.       ^ modelDependents at: anObject ifAbsent: [ ^ nil ]
  39. |
  40.    broadcast: aSymbol ! theseDependents !
  41.       theseDependents <- modelDependents at: self ifAbsent: [ nil ].
  42.       
  43.       (theseDependents isNotNil)
  44.          ifTrue: [theseDependents do: [ :d | d perform: aSymbol ] ]
  45. |
  46.    broadcast: aSymbol with: anObject ! theseDependents !
  47.       theseDependents <- modelDependents at: self ifAbsent: [ nil ].
  48.       
  49.       (theseDependents isNotNil)
  50.          ifTrue: [theseDependents do: [ :d | d perform: aSymbol with: anObject ] ]
  51. |
  52.    myDependents
  53.      " Answer the receiver's dependents or nil. "
  54.  
  55.      ^ modelDependents at: self ifAbsent: [nil]
  56. |
  57.    myDependents: dependentsOrNil
  58.      " Set the receiver's dependents to aDependentsCollection "
  59.  
  60.      (dependentsOrNil == nil)
  61.         ifTrue: [modelDependents removeKey: self ifAbsent: []]
  62.        ifFalse: [modelDependents at: self put: dependentsOrNil]
  63. |
  64.    postCopy
  65.      " Do not copy the dependents list. "
  66.  
  67.      super postCopy.
  68.  
  69.      self breakDependents
  70. |
  71.    initialize
  72.      modelDependents <- nil.
  73.      modelAdaptors   <- nil.
  74.      haveAChange     <- 0. 
  75. |
  76.    addDependent: anObject
  77.       "Make the given object one of the receiver's dependents."
  78.  
  79.       (modelDependents == nil)
  80.          ifTrue: [ modelDependents <- Array new: 1.
  81.                    modelDependents at: 1 put: anObject
  82.                  ]
  83.         ifFalse: [ "done if anObject is already a dependent"
  84.                    modelDependents do: [:o | (o == anObject) ifTrue: [^ self] ].
  85.                    "otherwise, add it"
  86.                    modelDependents <- modelDependents grow: anObject
  87.                  ].
  88. |
  89.    changeComplete
  90.       (haveAChange > 0)
  91.          ifTrue:  [ haveAChange <- haveAChange - 1.
  92.                     ^ false ]
  93.          ifFalse: [ ^ true ]
  94. |
  95.    changeMade
  96.       haveAChange <- haveAChange + 1
  97. |
  98.    release
  99.       self breakDependents
  100. |
  101.    breakDependents
  102.       " Remove all of the receiver's dependents "
  103.  
  104.       self myDependents: nil
  105. |
  106.    onChangeSend: aSelector to: aDependent
  107.       self expressInterestIn: #value for: aDependent sendBack: aSelector
  108. |
  109.    expressInterestIn: anAspect for: anObject sendBack: aSelector 
  110.       ! dt deps !
  111.  
  112.       " Arrange for anObject to receive a message named aSelector when
  113.       * I signal that my attribute anAspect has changed.
  114.       "
  115.       dt <- DependencyTransformer new.
  116.  
  117.       dt setReceiver: anObject aspect: anAspect selector: aSelector.
  118.     
  119.       deps <- self myDependents.
  120.  
  121.       (deps class == DependentsCollection)
  122.          ifTrue: [deps includes: dt]
  123.         ifFalse: [(deps = dt)
  124.                     ifTrue: [ ^ self ] ].
  125.  
  126.       self addDependent: dt
  127. |
  128.    retractInterestIn: anAspect for: anObject ! deps !
  129.       " Undo a send of expressInterestIn:for:sendBack: "
  130.  
  131.       deps <- self myDependents.
  132.  
  133.       (deps == nil)
  134.          ifTrue: [ ^ self ].
  135.  
  136.       (deps class == DependencyTransformer and: [deps matches: anObject forAspect: anAspect])
  137.          ifTrue: [ ^ self removeDependent: deps].
  138.  
  139.       (deps class == DependentsCollection) 
  140.          ifFalse: [ ^ self ].
  141.  
  142.       1 to: deps size do: [:i | ((deps at: i) class == DependencyTransformer and:
  143.                                    [(deps at: i) matches: anObject forAspect: anAspect])
  144.                         ifTrue: [ ^ self removeDependent: (deps at: i) ] ]
  145. |
  146.    asDependentsAsCollection
  147.       " Answer the receiver, considered as a collection of dependents, 
  148.       * as a real Collection.  Since the receiver represents
  149.       * a singleton dependents collection, answer a Collection 
  150.       * containing only    the receiver. 
  151.       "
  152.       ^ Array with: self
  153. |
  154.    asDependentsWith: anObject
  155.       " Answer the receiver, considered as a collection of dependents,
  156.       * with anObject added.  Since the receiver represents a 
  157.       * singleton dependents collection, answer a Collection 
  158.       * containing the receiver and anObject. 
  159.       "
  160.       ^ DependentsCollection with: self with: anObject
  161. |
  162.    asDependentsWithout: anObject
  163.       " Answer the receiver, considered as a collection of dependents,
  164.       * with the first occurrence of anObject (if any) removed.
  165.       * If anObject does not occur in the receiver, answer the receiver. 
  166.       * Since the receiver represents a    singleton dependents collection,
  167.       * answer either the receiver or nil. 
  168.       "
  169.       ^ anObject == self
  170.            ifTrue: [ nil  ]
  171.           ifFalse: [ self ]
  172. |
  173.    canDiscardEdits
  174.       " Answer true if none of the views on this 
  175.       * model has unaccepted edits that matter.
  176.       "
  177.       (modelDependents == nil)
  178.          ifTrue: [^ true].
  179.  
  180.       (haveAChange < 1)
  181.          ifTrue: [ ^ true ].
  182.          
  183.       ^ false
  184. |
  185.    dependents: dependentsOrNil
  186.      " Set the receivers dependents. "
  187.  
  188.      modelDependents <- dependentsOrNil
  189. |
  190.    dependents
  191.       " Answer a collection of objects that are 'dependent' 
  192.       * on the receiver; that is, all objects that should 
  193.       * be notified if the receiver changes.
  194.       "
  195.  
  196.       (modelDependents == nil) 
  197.          ifTrue: [^ #() ].
  198.  
  199.       ^ modelDependents
  200. |
  201.    hasUnacceptedEdits
  202.       " Answer true if any of the views on this model 
  203.       * has unaccepted edits.
  204.       "
  205.  
  206.       (modelDependents == nil)
  207.           ifTrue: [^ false].
  208.       
  209.       (haveAChange > 1)
  210.          ifTrue: [ ^ true ].
  211.          
  212.       ^ false
  213. |
  214.    removeDependent: anObject ! newDependents !
  215.  
  216.       "Remove the given object as one of the receiver's dependents."
  217.  
  218.       (modelDependents == nil) 
  219.          ifTrue: [^ self].
  220.  
  221.       newDependents <- modelDependents select: [:d | (d == anObject) not].
  222.  
  223.       (newDependents isEmpty)
  224.          ifTrue:  [modelDependents <- nil]
  225.          ifFalse: [modelDependents <- newDependents].
  226. |
  227.    topController
  228.       " Find the first top controller on me.  Is there any danger
  229.       * of their being two with the same model?  Any danger 
  230.       * from ungarbage collected old controllers?
  231.       "
  232.       modelDependents ifNil: [^ nil].
  233.  
  234.       modelDependents do: [:v | ((v isKindOf: Controller) 
  235.                                     and: [v isInWorld]) 
  236.            
  237.                              ifTrue: [^ v] ].
  238.  
  239.       modelDependents do: [:v | (v superController) 
  240.                               ifNil: [(v model == self) 
  241.                                          ifTrue: [ ^ v ] ] ].
  242.  
  243.       ^ nil
  244. |
  245.    linkMethod: classAndMethod
  246.  
  247.       "Make a message list and put this method in it"
  248.  
  249.       (linkedMethods isNil)
  250.          ifTrue: [ linkedMethods <- KeyedCollection new ].
  251.  
  252.       linkedMethods add: classAndMethod
  253. |
  254.    value   "SubClasses must override this: "
  255.       super subclassResponsibility: 'value'.
  256.  
  257.       ^ nil
  258. |
  259.    new
  260.       modelDependents <- DependentsCollection new.
  261.       modelAdaptors   <- Array new.
  262.       linkedMethods   <- KeyedCollection new.
  263.       haveAChange     <- 0.
  264. |
  265.    perform: selector orSendTo: otherTarget
  266.       " Selector was just chosen from a Control by a User.  
  267.       * If I can respond, then perform it on myself.  If not, send 
  268.       * it to otherTarget.
  269.       " 
  270.       ^ otherTarget perform: selector.
  271. |
  272.    windowIsClosing
  273.       " This message is used to inform a model(s) that its window
  274.       * is closing.  Most models do nothing, but some, must do 
  275.       * some cleanup.  Note that this mechanism must be used 
  276.       * with care by models that support multiple views, since 
  277.       * one view may be closed while others have been left open.
  278.       * Default response is no-op:
  279.       "
  280.       ^ nil
  281. |
  282.    modelSleep
  283.       " A window with me as model is being exited or collapsed or closed.
  284.       * Default response is no-op:
  285.       "
  286.       ^ nil
  287. |
  288.    modelWakeUp
  289.       " A window with me as model is being entered or expanded.  
  290.       * Default response is no-op:
  291.       "
  292.       ^ nil
  293. |
  294.    modelWakeUpIn: aWindow
  295.       " A window with me as model is being entered or expanded.  
  296.       * Default response is no-op:
  297.       " 
  298.       self modelWakeUp
  299. |
  300.    contentsChanged
  301.       self changed: #contentsChanged
  302. |
  303.    okToChange
  304.       " Allows a controller to ask this of any model "
  305.  
  306.       ^ true
  307. |
  308.    changed
  309.       " Receiver changed in a general way; inform all the dependents by 
  310.       * sending each dependent an update: message.
  311.       "
  312.       self changed: nil
  313. |
  314.    changed: anAspectSymbol
  315.  
  316.       " Receiver changed.  The change is denoted by the argument
  317.       * anAspectSymbol.  Usually the argument is a Symbol that 
  318.       * is part of the dependent's change protocol. Inform all 
  319.       * of the dependents.
  320.       "
  321.       self changed: anAspectSymbol with: nil
  322. |
  323.    changed: anAspectSymbol with: aParameter
  324.       self modelDependents update: anAspectSymbol with: aParameter from: self
  325. |
  326.    update: anAspectSymbol with: aParameter from: aSender
  327.       ^ self update: anAspectSymbol with: aParameter
  328. |
  329.    update: anAspectSymbol with: aParameter
  330.       ^ self update: anAspectSymbol
  331. |
  332.    update: anAspectSymbol
  333.       " Receive a change notice from an object of whom the 
  334.       * receiver is a dependent.  The default behavior is 
  335.       * to do nothing; a subclass might want 
  336.       * to change itself in some way.
  337.       "
  338.       ^ self
  339. ]
  340.